﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RedisDemo
{
    public class RedisUtil
    {
        public RedisClient client = null;

        /// <summary>
        /// 开启redis服务
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (Process.GetProcessesByName("redis-server.exe").Length > 0)
            {
                return false;
            }
            Process process = new Process();
            process.StartInfo.WorkingDirectory = @"F:\Redis";
            process.StartInfo.FileName = @"F:\Redis\startup.bat";
            process.StartInfo.CreateNoWindow = false;
            process.StartInfo.UseShellExecute = false;
            process.Start();
            return true;
        }

        /// <summary>
        /// 关闭redis服务
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            bool flag = false;
            foreach (Process process in Process.GetProcesses())
            {
                if (process.ProcessName.Contains("redis-server"))
                {
                    process.Kill();
                    flag = true;
                }
            }
            return flag;
        }

        /// <summary>
        /// 连接redis服务
        /// </summary>
        /// <returns></returns>
        public void Connect()
        {
            if (client == null)
            {
                client = new RedisClient("127.0.0.1", 6379);
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            if (client != null)
            {
                client.Quit();
            }
        }

        /// <summary>
        /// 所有键值对
        /// </summary>
        /// <returns></returns>
        public List<string> AllKeyValue()
        {
            IEnumerable<string> keys = client.ScanAllKeys();
            List<string> result = new List<string>();
            foreach (string key in keys)
            {
                string value = "";
                string type = client.Type(key).ToLower();
                int len;
                byte[][] buffer;
                switch (type)
                {
                    case "string":
                        value = client.GetValue(key);
                        break;
                    case "hash":
                        buffer = client.HGetAll(key);
                        value += "{";
                        for (int i = 0; i < buffer.Length; i += 2)
                        {
                            value += $"{Encoding.UTF8.GetString(buffer[i])}={Encoding.UTF8.GetString(buffer[i + 1])}";
                            if (i + 2 < buffer.Length)
                            {
                                value += ",";
                            }
                        }
                        value += "}";
                        break;
                    case "list":
                        len = (int)client.LLen(key);
                        buffer = client.LRange(key, 0, len);
                        value += "[";
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            value += $"{Encoding.UTF8.GetString(buffer[i])}";
                            if (i + 1 < buffer.Length)
                            {
                                value += ",";
                            }
                        }
                        value += "]";
                        break;
                    case "set":
                        buffer = client.SMembers(key);
                        value += "{";
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            value += $"{Encoding.UTF8.GetString(buffer[i])}";
                            if (i + 1 < buffer.Length)
                            {
                                value += ",";
                            }
                        }
                        value += "}";
                        break;
                    case "zset":
                        len = (int)client.ZCard(key);
                        buffer = client.ZRange(key, 0, len);
                        value += "{";
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            value += $"{Encoding.UTF8.GetString(buffer[i])}";
                            if (i + 1 < buffer.Length)
                            {
                                value += ",";
                            }
                        }
                        value += "}";
                        break;
                    default:
                        break;
                }
                result.Add($"type={type},key={key},value={value}");
            }
            return result;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public void Add<T>(T t) where T : IAdd
        {
            t.Add(client);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="key"></param>
        public void Delete(string key)
        {
            client.Del(key);
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string Search(string key)
        {
            List<string> result = AllKeyValue();
            string pattern = $"key={key}";
            foreach(string keyvalue in result)
            {
                if (keyvalue.Contains(pattern))
                {
                    return keyvalue;
                }
            }
            return "";
        }
    }

    public interface IAdd
    {
        void Add(RedisClient client);
    }

    public class StringItem : IAdd
    {
        public string key;
        public string value;
        public StringItem(string key, string value)
        {
            this.key = key;
            this.value = value;
        }

        public void Add(RedisClient client)
        {
            client.Set(key, value);
        }
    }

    public class HashItem : IAdd
    {
        public string hashId;
        public Dictionary<string, string> pairs = new Dictionary<string, string>();
        public HashItem(string hashId, Dictionary<string, string> pairs)
        {
            this.hashId = hashId;
            this.pairs = pairs;
        }

        public void Add(RedisClient client)
        {
            byte[][] ks = new byte[pairs.Count][];
            byte[][] vs = new byte[pairs.Count][];
            int i = 0;
            foreach (string key in pairs.Keys)
            {
                ks[i] = Encoding.UTF8.GetBytes(key.ToString());
                vs[i] = Encoding.UTF8.GetBytes(pairs[key].ToString());
            }
            client.HMSet(hashId, ks, vs);
        }
    }

    public class ListItem : IAdd
    {
        public string listId;
        public string value;
        public ListItem(string listId, string value)
        {
            this.listId = listId;
            this.value = value;
        }
        public void Add(RedisClient client)
        {
            client.LPush(listId, Encoding.UTF8.GetBytes(value));
        }
    }

    public class SetItem : IAdd
    {
        public string setId;
        public string value;
        public SetItem(string setId, string value)
        {
            this.setId = setId;
            this.value = value;
        }

        public void Add(RedisClient client)
        {
            client.SAdd(setId, Encoding.UTF8.GetBytes(value));
        }
    }

    public class ZSetItem : IAdd
    {
        public string setId;
        public double score;
        public string value;
        public ZSetItem(string setId, double score, string value)
        {
            this.setId = setId;
            this.score = score;
            this.value = value;
        }
        public void Add(RedisClient client)
        {
            client.ZAdd(setId, score, Encoding.UTF8.GetBytes(value));
        }
    }
}
